package com.shrikanthravi.customnavigationdrawer2.widget;

import com.shrikanthravi.customnavigationdrawer2.ResourceTable;
import com.shrikanthravi.customnavigationdrawer2.data.MenuItem;
import com.shrikanthravi.customnavigationdrawer2.utils.AttrUtils;
import com.shrikanthravi.customnavigationdrawer2.utils.JUtils;
import com.shrikanthravi.customnavigationdrawer2.utils.ResourceUtil;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class SNavigationDrawer extends DependentLayout {
    protected Context mContext;
    protected LayoutScatter mLayoutInflater;
    protected List<MenuItem> menuItemList;
    protected DependentLayout rootLayout, appbarRL;
    protected DirectionalLayout containerCV;
    protected DirectionalLayout menuDirect;
    protected Text appbarTitleTV;
    protected Image menuIV;
    protected ScrollView menuSV;
    protected DirectionalLayout menuLL;
    public StackLayout containerLL;
    private int appbarColor = Color.WHITE.getValue();
    private int appbarTitleTextColor = Color.BLACK.getValue();
    private int menuItemSemiTransparentColor = new Color(ResourceTable.Color_transparent_black_percent_60).getValue();
    private int navigationDrawerBackgroundColor = Color.WHITE.getValue();
    private int primaryMenuItemTextColor = Color.WHITE.getValue();
    private int secondaryMenuItemTextColor = Color.BLACK.getValue();
    private int appbarTitleTextSize = 20;
    private int primaryMenuItemTextSize = 20;
    private int secondaryMenuItemTextSize = 20;
    private final HashMap<String, DependentLayout> backgroundCVMap = new HashMap<>();
    private final HashMap<String, Text> titleTVMap = new HashMap<>();
    private boolean navOpen = false;
    private int currentPos = 0;
    float centerX, centerY;

    public enum State {
        STATE_OPEN, STATE_CLOSED, STATE_OPENING, STATE_CLOSING
    }

    private OnHamMenuClickListener onHamMenuClickListener;
    private OnMenuItemClickListener onMenuItemClickListener;
    private DrawerListener drawerListener;

    public SNavigationDrawer(Context context) {
        this(context, null);
    }

    public SNavigationDrawer(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public SNavigationDrawer(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context);
        setAttributes(attrSet);
    }

    @Override
    public void addComponent(Component child) {
        if (containerLL == null) {
            super.addComponent(child);
        } else {
            containerLL.addComponent(child);
        }
    }

    protected void init(Context context) {
        mContext = context;
        mLayoutInflater = LayoutScatter.getInstance(context);
        Component rootView = mLayoutInflater.parse(ResourceTable.Layout_widget_navigation_drawer, this, true);
        rootLayout = (DependentLayout) rootView.findComponentById(ResourceTable.Id_rootLayout);
        appbarRL = (DependentLayout) rootView.findComponentById(ResourceTable.Id_appBarRL);
        containerCV = (DirectionalLayout) rootView.findComponentById(ResourceTable.Id_containerCV);
        menuDirect = (DirectionalLayout) rootView.findComponentById(ResourceTable.Id_menuDirect);
        appbarTitleTV = (Text) rootView.findComponentById(ResourceTable.Id_appBarTitleTV);
        menuIV = (Image) rootView.findComponentById(ResourceTable.Id_menuIV);
        menuSV = (ScrollView) rootView.findComponentById(ResourceTable.Id_menuSV);
        menuLL = (DirectionalLayout) rootView.findComponentById(ResourceTable.Id_menuLL);
        containerLL = (StackLayout) rootView.findComponentById(ResourceTable.Id_containerLL);
        menuItemList = new ArrayList<>();
        menuIV.setClickedListener(component -> JUtils.preventRepeatClick(() -> {
            hamMenuClicked();
            if (navOpen) {
                closeDrawer();
            } else {
                openDrawer();
            }
        }));
    }

    protected void initMenu() {
        for (int i = 0; i < menuItemList.size(); i++) {
            Component view = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_menu_row_item, null, false);
            Text titleTV = (Text) view.findComponentById(ResourceTable.Id_titleTV);
            Text titleTV1 = (Text) view.findComponentById(ResourceTable.Id_titleTV1);
            Image backgroundIV = (Image) view.findComponentById(ResourceTable.Id_backgroundIV);
            DependentLayout backgroundCV = (DependentLayout) view.findComponentById(ResourceTable.Id_backgroundCV);
            Component tintView = view.findComponentById(ResourceTable.Id_tintView);
            ShapeElement shapeElement = new ShapeElement();
            shapeElement.setRgbColor(RgbColor.fromArgbInt(menuItemSemiTransparentColor));
            tintView.setBackground(shapeElement);
            titleTV1.setTextColor(new Color(primaryMenuItemTextColor));
            titleTV.setTextSize(secondaryMenuItemTextSize);
            titleTV1.setTextSize(primaryMenuItemTextSize);
            final DependentLayout rootRL = (DependentLayout) view.findComponentById(ResourceTable.Id_rootRL);
            backgroundCVMap.put("cv" + i, backgroundCV);
            titleTVMap.put("tv" + i, titleTV);
            if (i >= 1) {
                AnimatorProperty animatorProperty = backgroundCV.createAnimatorProperty();
                animatorProperty.moveFromX(0).moveToX(-backgroundCV.getWidth()).setDuration(0).start();
                titleTV.setVisibility(Component.VISIBLE);
                backgroundCV.setVisibility(Component.HIDE);
            }
            rootRL.setTag(i);
            rootRL.setClickedListener(component -> JUtils.preventRepeatClick(() -> {
                if (currentPos != Integer.parseInt(component.getTag().toString())) {
                    //获取当前的item
                    final DependentLayout backCV1 = backgroundCVMap.get(("cv" + currentPos));
                    final Text title1 = titleTVMap.get(("tv" + currentPos));
                    AnimatorProperty animatorProperty = backCV1.createAnimatorProperty();
                    animatorProperty.moveFromX(0).moveToX(-backCV1.getWidth()).setDuration(300).start();
                    //点击的item
                    currentPos = Integer.parseInt(view.getTag().toString());
                    menuItemClicked(currentPos);
                    appbarTitleTV.setText(menuItemList.get(currentPos).getTitle());
                    final DependentLayout backCV2 = backgroundCVMap.get(("cv" + currentPos));
                    final Text title2 = titleTVMap.get(("tv" + currentPos));
                    backCV2.setVisibility(Component.INVISIBLE);
                    AnimatorProperty animatorProperty1 = backCV2.createAnimatorProperty();
                    animatorProperty1.moveFromX(0).moveToX(-backCV2.getWidth()).setDuration(0).start();
                    AnimatorProperty animatorProperty2 = backCV2.createAnimatorProperty();
                    animatorProperty2.moveFromX(-backCV2.getWidth()).moveToX(0).setDuration(300).start();
                    title2.setVisibility(Component.HIDE);
                    backCV2.setVisibility(Component.VISIBLE);
                    new EventHandler(EventRunner.getMainEventRunner()).postTask(() -> {
                        backCV1.setVisibility(Component.HIDE);
                        title1.setVisibility(Component.VISIBLE);
                    }, 300);

                } else {
                    menuItemClicked(currentPos);
                }
                closeDrawer();
            }));
            backgroundIV.setImageElement(new ResourceUtil(mContext).getImageDrawable(menuItemList.get(i).getImageId()));
            titleTV.setText(menuItemList.get(i).getTitle());
            titleTV1.setText(menuItemList.get(i).getTitle());
            menuLL.addComponent(view);
        }
    }

    public interface OnHamMenuClickListener {
        void onHamMenuClicked();
    }

    public interface OnMenuItemClickListener {
        void onMenuItemClicked(int position);
    }

    public interface DrawerListener {
        void onDrawerOpening();

        void onDrawerClosing();

        void onDrawerOpened();

        void onDrawerClosed();

        void onDrawerStateChanged(State newState);
    }

    public OnHamMenuClickListener getOnHamMenuClickListener() {
        return onHamMenuClickListener;
    }

    public void setOnHamMenuClickListener(OnHamMenuClickListener onHamMenuClickListener) {
        this.onHamMenuClickListener = onHamMenuClickListener;
    }

    public OnMenuItemClickListener getOnMenuItemClickListener() {
        return onMenuItemClickListener;
    }

    public void setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {
        this.onMenuItemClickListener = onMenuItemClickListener;
    }

    public DrawerListener getDrawerListener() {
        return drawerListener;
    }

    public void setDrawerListener(DrawerListener drawerListener) {
        this.drawerListener = drawerListener;
    }

    protected void hamMenuClicked() {
        if (onHamMenuClickListener != null) {
            onHamMenuClickListener.onHamMenuClicked();
        }
    }

    protected void menuItemClicked(int position) {
        if (onMenuItemClickListener != null) {
            onMenuItemClickListener.onMenuItemClicked(position);
        }
    }

    protected void drawerOpened() {
        if (drawerListener != null) {
            drawerListener.onDrawerOpened();
            drawerListener.onDrawerStateChanged(State.STATE_OPEN);
        }
    }

    protected void drawerClosed() {
        if (drawerListener != null) {
            drawerListener.onDrawerClosed();
            drawerListener.onDrawerStateChanged(State.STATE_CLOSED);
            menuDirect.setVisibility(Component.INVISIBLE);
        }
    }

    protected void drawerOpening() {
        if (drawerListener != null) {
            drawerListener.onDrawerOpening();
            drawerListener.onDrawerStateChanged(State.STATE_OPENING);
            menuDirect.setVisibility(Component.VISIBLE);
        }
    }

    protected void drawerClosing() {
        if (drawerListener != null) {
            drawerListener.onDrawerClosing();
            drawerListener.onDrawerStateChanged(State.STATE_CLOSING);
        }
    }

    protected void closeDrawer() {
        drawerClosing();
        navOpen = false;
        menuIV.setImageElement(new ResourceUtil(mContext).getImageDrawable(ResourceTable.Media_menu));
        //添加动画
        AnimatorProperty animatorProperty = menuIV.createAnimatorProperty();
        animatorProperty.rotate(180).setDuration(300).start();
        //设置appbarTitleTV动画
        AnimatorValue animatorValue1 = new AnimatorValue();
        animatorValue1.setDuration(500);
        animatorValue1.setValueUpdateListener((animatorValue, value) -> appbarTitleTV.setTranslationX((centerX + menuIV.getWidth() + menuIV.getWidth() / 4f + appbarTitleTV.getWidth() / 2f - appbarRL.getWidth() / 2f) * (1 - value)));
        animatorValue1.start();
        //设置containerCV动画
        AnimatorValue animatorValue2 = new AnimatorValue();
        animatorValue2.setDuration(500);
        animatorValue2.setValueUpdateListener((animatorValue, value) -> {
            containerCV.setTranslationX((((rootLayout.getWidth() / 8f) + (rootLayout.getWidth() / 2f)) * (1 - value)));
            containerCV.setTranslationY(250 * (1 - value));
        });
        animatorValue2.start();
        new EventHandler(EventRunner.getMainEventRunner()).postTask(this::drawerClosed, 500);
    }

    protected void openDrawer() {
        drawerOpening();
        navOpen = true;
        menuIV.setImageElement(new ResourceUtil(mContext).getImageDrawable(ResourceTable.Media_arrow_left));
        //添加动画
        AnimatorProperty animatorProperty = menuIV.createAnimatorProperty();
        animatorProperty.rotate(360).setDuration(300).start();
        //设置appbarTitleTV动画
        AnimatorValue animatorValue1 = new AnimatorValue();
        animatorValue1.setDuration(500);
        animatorValue1.setValueUpdateListener((animatorValue, value) -> appbarTitleTV.setTranslationX((centerX + menuIV.getWidth() + menuIV.getWidth() / 4f + appbarTitleTV.getWidth() / 2f - appbarRL.getWidth() / 2f) *  value));
        animatorValue1.start();
        //设置containerCV动画
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(500);
        animatorValue.setValueUpdateListener((animatorValue2, value) -> {
            containerCV.setTranslationX(((rootLayout.getWidth() / 8f + rootLayout.getWidth() / 2f) * value));
            containerCV.setTranslationY(250 * value);
        });
        animatorValue.start();
        new EventHandler(EventRunner.getMainEventRunner()).postTask(this::drawerOpened, 500);
    }

    protected void setAttributes(AttrSet attrs) {
        setAppbarColor(AttrUtils.getColorFromAttr(attrs, "appbarColor", appbarColor));
        setAppbarTitleTextColor(AttrUtils.getColorFromAttr(attrs, "appbarTitleTextColor", appbarTitleTextColor));
        setNavigationDrawerBackgroundColor(AttrUtils.getColorFromAttr(attrs, "navigationDrawerBackgroundColor", navigationDrawerBackgroundColor));
        setAppbarTitleTextSize(AttrUtils.getDimensionFromAttr(attrs, "appbarTitleTextSize", (int) JUtils.vp2px(mContext, appbarTitleTextSize)));
        this.menuItemSemiTransparentColor = AttrUtils.getColorFromAttr(attrs, "menuItemSemiTransparentColor", menuItemSemiTransparentColor);
        this.primaryMenuItemTextColor = AttrUtils.getColorFromAttr(attrs, "primaryMenuItemTextColor", primaryMenuItemTextColor);
        this.secondaryMenuItemTextColor = AttrUtils.getColorFromAttr(attrs, "secondaryMenuItemTextColor", secondaryMenuItemTextColor);
        this.primaryMenuItemTextSize = AttrUtils.getDimensionFromAttr(attrs, "primaryMenuItemTextSize", (int) JUtils.vp2px(mContext, primaryMenuItemTextSize));
        this.secondaryMenuItemTextSize = AttrUtils.getDimensionFromAttr(attrs, "secondaryMenuItemTextSize", (int) JUtils.vp2px(mContext, secondaryMenuItemTextSize));
    }


    /**
     * 设置appbar的标题
     *
     * @param name 标题
     */
    public void setAppbarTitleTV(String name) {
        appbarTitleTV.setText(name);
    }


    /**
     * 菜单是否打开
     * @return 导航菜单时候打开
     */
    public boolean isDrawerOpen() {
        return navOpen;
    }


    /**
     * 添加菜单item
     *
     * @param menuItem 菜单item数据
     */
    public void addMenuItem(MenuItem menuItem) {
        if (menuItemList != null) {
            menuItemList.add(menuItem);
            menuLL.removeAllComponents();
            initMenu();
        }
    }


    /**
     * 获取菜单数据
     * @return 菜单数据集
     */
    public List<MenuItem> getMenuItemList() {
        return menuItemList;
    }


    /**
     * 设置菜单的数据
     *
     * @param menuItemList 数据集合
     */
    public void setMenuItemList(List<MenuItem> menuItemList) {
        this.menuItemList = menuItemList;
        initMenu();
    }


    /**
     * 获取appbar的颜色
     * @return 获取appbar的颜色
     */
    public int getAppbarColor() {
        return appbarColor;
    }


    /**
     * 设置appbar的颜色
     *
     * @param appbarColor 颜色值
     */
    public void setAppbarColor(int appbarColor) {
        this.appbarColor = appbarColor;
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbColor.fromArgbInt(appbarColor));
        appbarRL.setBackground(shapeElement);
    }


    /**
     * 获取标题的颜色
     * @return 获取标题的颜色
     */
    public int getAppbarTitleTextColor() {
        return appbarTitleTextColor;
    }


    /**
     * 设置appbar的标题颜色
     *
     * @param appbarTitleTextColor 颜色值
     */
    public void setAppbarTitleTextColor(int appbarTitleTextColor) {
        this.appbarTitleTextColor = appbarTitleTextColor;
        appbarTitleTV.setTextColor(new Color(appbarTitleTextColor));
    }


    /**
     * 获取标题的大小
     * @return 获取标题的大小
     */
    public float getAppbarTitleTextSize() {
        return appbarTitleTextSize;
    }


    /**
     * 设置appbar的标题大小
     *
     * @param appbarTitleTextSize 大小
     */
    public void setAppbarTitleTextSize(int appbarTitleTextSize) {
        this.appbarTitleTextSize = appbarTitleTextSize;
        appbarTitleTV.setTextSize(appbarTitleTextSize);
    }


    /**
     * 获取菜单的背景透明度
     * @return 获取菜单的背景透明度
     */
    public int getMenuItemSemiTransparentColor() {
        return menuItemSemiTransparentColor;
    }


    /**
     * 设置菜单item的的背景透明度
     *
     * @param menuItemSemiTransparentColor 透明度颜色
     */
    public void setMenuItemSemiTransparentColor(int menuItemSemiTransparentColor) {
        this.menuItemSemiTransparentColor = menuItemSemiTransparentColor;
        menuLL.removeAllComponents();
        initMenu();
    }


    /**
     * 导航菜单的背景颜色
     * @return 导航菜单的背景颜色
     */
    public int getNavigationDrawerBackgroundColor() {
        return navigationDrawerBackgroundColor;
    }


    /**
     * 设置导航菜单的背景颜色
     *
     * @param navigationDrawerBackgroundColor 颜色值
     */
    public void setNavigationDrawerBackgroundColor(int navigationDrawerBackgroundColor) {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbColor.fromArgbInt(navigationDrawerBackgroundColor));
        rootLayout.setBackground(shapeElement);
        this.navigationDrawerBackgroundColor = navigationDrawerBackgroundColor;
    }


    /**
     * 获取主菜单的item颜色
     * @return 获取主菜单的item颜色
     */
    public int getPrimaryMenuItemTextColor() {
        return primaryMenuItemTextColor;
    }


    /**
     * 设置主菜单item的文本颜色
     *
     * @param primaryMenuItemTextColor 颜色
     */
    public void setPrimaryMenuItemTextColor(int primaryMenuItemTextColor) {
        this.primaryMenuItemTextColor = primaryMenuItemTextColor;
        menuLL.removeAllComponents();
        initMenu();
    }


    /**
     * 副菜单的item颜色
     * @return 副菜单的item颜色
     */
    public int getSecondaryMenuItemTextColor() {
        return secondaryMenuItemTextColor;
    }


    /**
     * 设置副菜单item的文本颜色
     *
     * @param secondaryMenuItemTextColor 颜色
     */
    public void setSecondaryMenuItemTextColor(int secondaryMenuItemTextColor) {
        this.secondaryMenuItemTextColor = secondaryMenuItemTextColor;
        menuLL.removeAllComponents();
        initMenu();
    }


    /**
     * 主菜单的item标题大小
     * @return 主菜单的item标题大小
     */
    public float getPrimaryMenuItemTextSize() {
        return primaryMenuItemTextSize;
    }


    /**
     * 设置主菜单的item字体大小
     *
     * @param primaryMenuItemTextSize 字体大小
     */
    public void setPrimaryMenuItemTextSize(int primaryMenuItemTextSize) {
        this.primaryMenuItemTextSize = (int) JUtils.vp2px(mContext, primaryMenuItemTextSize);
        menuLL.removeAllComponents();
        initMenu();
    }


    /**
     * 副菜单的标题大小
     * @return 副菜单的标题大小
     */
    public float getSecondaryMenuItemTextSize() {
        return secondaryMenuItemTextSize;
    }


    /**
     * 设置副菜单的item字体大小
     *
     * @param secondaryMenuItemTextSize 字体大小
     */
    public void setSecondaryMenuItemTextSize(int secondaryMenuItemTextSize) {
        this.secondaryMenuItemTextSize = (int) JUtils.vp2px(mContext, secondaryMenuItemTextSize);
        menuLL.removeAllComponents();
        initMenu();
    }


    /**
     * 设置appbar的标题字体样式
     *
     * @param titleTypeface 字体样式
     */
    public void setAppbarTitleTypeface(Font titleTypeface) {
        appbarTitleTV.setFont(titleTypeface);
    }
}
